package de.blitzcoder.collide;

import de.blitzcoder.collide.icons.Icon;
import de.blitzcoder.collide.util.KeyStrokeUtil;
import de.blitzcoder.collide.util.OS;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 *
 * @author blitzcoder
 */
public class Menu extends JMenuBar {

   
    private HashMap<String, JMenuItem> idMap;
    private String script;
    private GroovyShell shell = new GroovyShell();

    public Menu() {

        idMap = new HashMap<String, JMenuItem>();
        try {
            // Create Docbuilder
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            // Parse file
            Document doc = builder.parse("menu.xml");

            NodeList nodes = doc.getChildNodes().item(1).getChildNodes();
            System.out.println(nodes.getLength());
            for (int i = 0; i < nodes.getLength(); i++) {
                Node node = nodes.item(i);

                if (node.getNodeName().equals("script")) {
                    script = node.getTextContent();
                } else if (node.getNodeName().equals("menu")) {
                    parseXmlNode(node,this);
                }
                
            }
        } catch (Exception ex) {
            throw new Error(ex);
        }

    }



    private void parseXmlNode(Node node,JComponent parent) {

        String name = node.getNodeName();
        NamedNodeMap map = node.getAttributes();

        if (name.startsWith("#"))
            return;

        if (name.equals("separator")) {
            if (parent instanceof JMenu) {
                ((JMenu)parent).addSeparator();
                return;
            } else {
                throw new Error("Separators are only allowed in JMenus");
            }
        }

        Node title = null;
        Node icon = null;
        Node shortcut = null;
        Node id = null;
        Node nmenomic = null;
        String code = null;

        JMenuItem item = null;

        if (name.equals("item") || name.equals("checkbox") || name.equals("menu")) {

            // Parse Standard values
            title = map.getNamedItem("title");
            icon = map.getNamedItem("icon");
            id = map.getNamedItem("id");
            nmenomic = map.getNamedItem("mnemonic");

        }

        if (name.equals("item") || name.equals("checkbox")) {
            shortcut = map.getNamedItem("shortcut");
            code = node.getTextContent();
        }

        String titleString = title.getNodeValue().replace("_", "&");

        if (name.equals("item")) {
            item = new JMenuItem(titleString);
        }

        if (name.equals("checkbox")) {
            item = new JCheckBoxMenuItem(titleString);

            // A start-state can be given by a config-variable
            if (map.getNamedItem("state") != null) {
                String key = map.getNamedItem("state").getNodeValue();
                ((JCheckBoxMenuItem)item).setSelected(Config.getBooleanProperty(key));
            }

        }
        
        if (name.equals("menu")) {
            item = new JMenu(titleString);
        }

        if (icon != null) {
            item.setIcon(Icon.load("menu/"+icon.getNodeValue()));
        }

        if (id != null) {
            idMap.put(id.getNodeValue(), item);
        }

        if (nmenomic != null) {
            String nm = nmenomic.getNodeValue();
            if (nm.length() == 1) {
                int c = nm.charAt(0);
                item.setMnemonic(c);
            }
        }

        if (code != null) {
            final String scriptCode = script+"\n"+code;
            item.addActionListener(new ActionListener() {
                private Script script = null;
                public void actionPerformed(ActionEvent e) {
                    if (e.getSource() instanceof JCheckBoxMenuItem)
                        shell.setVariable("state", new Boolean( ((JCheckBoxMenuItem)e.getSource()).getState() ) );
                    if (script == null)
                        script = shell.parse(scriptCode);
                    script.run();
                }
            });
        }

        if (shortcut != null) {
            KeyStroke s = KeyStrokeUtil.parseKeyStroke(shortcut.getNodeValue());

            if (OS.isMacOSX() && map.getNamedItem("shortcut_osx") != null)
                s = KeyStrokeUtil.parseKeyStroke(map.getNamedItem("shortcut_osx").getNodeValue());

            if (OS.isWindows() && map.getNamedItem("shortcut_windows") != null)
                s = KeyStrokeUtil.parseKeyStroke(map.getNamedItem("shortcut_windows").getNodeValue());

            if (OS.isLinux() && map.getNamedItem("shortcut_linux") != null)
                s = KeyStrokeUtil.parseKeyStroke(map.getNamedItem("shortcut_linux").getNodeValue());

            item.setAccelerator(s);

        }

        if (parent instanceof JMenuItem) {
            ((JMenuItem)parent).add(item);
        } else if (parent instanceof JMenuBar) {
            if (name.equals("menu")) {
                ((JMenuBar)parent).add((JMenu)item);
            } else {
                throw new Error("Only Menus can be at toplevel");
            }
        } else {
            throw new Error("Unknown parent");
        }

        if (name.equals("menu")) {

            NodeList list = node.getChildNodes();
            for (int i=0;i<list.getLength();i++) {

                Node n = list.item(i);
                parseXmlNode(n, (JMenu)item);

            }

        }

    }

    public JMenu getMenu(String id) {
        JMenuItem item = idMap.get(id);
        if (item == null)
            return null;
        return (JMenu)item;
    }
}
